package com.innjia.base.utils;

import com.xiaoleilu.hutool.crypto.SecureUtil;
import com.xiaoleilu.hutool.crypto.symmetric.SymmetricAlgorithm;
import com.xiaoleilu.hutool.crypto.symmetric.SymmetricCrypto;
import com.xiaoleilu.hutool.util.HexUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.MessageDigest;

/**
 * 用于数据脱敏
 * <br>
 * 2017-11-22
 *
 * @author zhouxianglh@gmail.com
 */
public class EncryptionUtils {
    public static final String TYPE_MD5 = "MD5";

    public static final String TYPE_SHA_1 = "SHA-1";

    /**
     * 脱敏字符,包含这个,说明已脱敏
     */
    public static final String ANON_STR = "*";

    /**
     * 身份证 显示前 1 位 + *(实际位数) + 后 1 位，如： 3****************3
     */
    public static final String TYPE_ID_CARD = "idCard";

    /**
     * 手机号	显示前 3 位 + **** + 后 4 位，如：137****9050
     */
    public static final String TYPE_MOBILE = "mobile";

    /**
     * 银行卡	显示前 6 位 + *(实际位数) + 后 4 位，如：622575******1496
     */
    public static final String TYPE_BANK_CARD = "bankCard";

    private static final Logger LOGGER = LoggerFactory.getLogger(EncryptionUtils.class);

    public static String aesEncrypt(String content, String hexKey) {
        byte[] key = HexUtil.decodeHex(hexKey);
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
        return aes.encryptHex(content).toUpperCase();
    }

    public static String aesDecrypt(String content, String hexKey) {
        byte[] key = HexUtil.decodeHex(hexKey);
        SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, key);
        return aes.decryptStr(content);
    }

    public static String getKey() {
        byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
        return HexUtil.encodeHexStr(key);
    }

    //    public static void main(String[] args) {
    //        TableInfo info = new TableInfo("123456789abcdefgh", null);
    //        EncryptionUtils.anno(info, "fieldName", EncryptionUtils.TYPE_BANK_CARD);//银行卡脱敏
    //        EncryptionUtils.anno(info, "fieldName", EncryptionUtils.TYPE_MOBILE);//手机号脱敏
    //        EncryptionUtils.anno(info, "fieldName", EncryptionUtils.TYPE_ID_CARD);//身份证脱敏
    //        EncryptionUtils.anno(info, "fieldName", null);//身份证脱敏
    //        System.out.println(info.getFieldName());
    //    }

    /**
     * 脱敏
     *
     * @param bean
     *         脱敏对象
     * @param property
     *         脱敏属性名
     * @param type
     *         操作类型,为空时按身份证标准来
     */
    public static void anno(Object bean, String property, String type) {
        try {
            if (null == bean) {
                return;
            }
            String value = BeanUtils.getProperty(bean, property);
            if (null == value) {
                return;
            }
            String newValue;
            int length = value.length();
            if (TYPE_MOBILE.equals(type) && length > 7) {
                newValue = org.apache.commons.lang3.StringUtils.join(value.substring(0, 3), value.substring(3, length - 4).replaceAll("[\\d\\D]", ANON_STR), value.substring(length - 4, length));
            } else if (TYPE_BANK_CARD.equals(type) && length > 10) {
                newValue = org.apache.commons.lang3.StringUtils.join(value.substring(0, 6), value.substring(6, length - 4).replaceAll("[\\d\\D]", ANON_STR), value.substring(length - 4, length));
            } else if (length > 2) {
                //身份证最严格,默认按身份证来
                newValue = org.apache.commons.lang3.StringUtils.join(value.substring(0, 1), value.substring(1, length - 1).replaceAll("[\\d\\D]", ANON_STR), value.substring(length - 1, length));
            } else {
                newValue = value;
            }
            BeanUtils.setProperty(bean, property, newValue);
        } catch (Exception e) {
            LOGGER.error("", e);
            throw new RuntimeException(e);
        }
    }

    public static String md5Encode(byte[] data) {
        return encodeByType(data, TYPE_MD5);
    }

    private static String encodeByType(byte[] data, String type) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance(type);
            return HexUtil.encodeHexStr(messageDigest.digest(data));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String sha1Encode(byte[] data) {
        return encodeByType(data, TYPE_SHA_1);
    }

}